home *** CD-ROM | disk | FTP | other *** search
/ Aminet 7 / Aminet 7 - August 1995.iso / Aminet / comm / net / plip_3812src.lha / plip / src / plip.c < prev    next >
C/C++ Source or Header  |  1995-03-24  |  27KB  |  1,217 lines

  1. /*
  2.  * plip.device - Parallel Line Internet Protocol
  3.  *
  4.  * A SANA-II networking device driver for two Amigas connected via their
  5.  * parallel ports.
  6.  *
  7.  * By Oliver Wagner with a little assistance of Michael Balzer.
  8.  * Copyright (c) 1993-1994 Oliver Wagner and Michael Balzer.
  9.  *
  10.  */
  11.  
  12. #include <proto/dos.h>
  13. #include <proto/exec.h>
  14. #include <proto/cia.h>
  15. #include <proto/misc.h>
  16. #include <proto/utility.h>
  17. #include <proto/timer.h>
  18. #include <devices/sana2.h>
  19. #include <hardware/cia.h>
  20. #include <resources/misc.h>
  21. #include <exec/memory.h>
  22. #include <dos/dostags.h>
  23. #include <string.h>
  24.  
  25. #define min __builtin_min
  26. #define max __builtin_max
  27. #define abs __builtin_abs
  28.  
  29. #define SERVER_TASK        "PLIP Server Task"
  30.  
  31. #define PLIP_MTU        2048
  32. #define PLIP_DEFMTU        1024
  33. #define PLIP_BPS        15000
  34. #define PLIP_HWTYPE        13
  35. #define PLIP_RETRIES        63
  36.  
  37. LONG plip_bps     = PLIP_BPS;
  38. LONG plip_mtu     = PLIP_DEFMTU;
  39. LONG plip_retries = PLIP_RETRIES;
  40.  
  41. #define ios2_Error ios2_Req.io_Error
  42. #define ios2_Flags ios2_Req.io_Flags
  43.  
  44. #define PKTFRAMESIZE 8
  45.  
  46. struct intdata {
  47. /*0*/    USHORT mode,pad1;
  48. /*4*/    ULONG recsig;            /* signals for receive */
  49. /*8*/    struct Task *sigtask;    /* device task to signal */
  50. /*12*/  struct ExecBase *SysBase; /* local sysbase copy for interrupt */
  51. };
  52.  
  53. struct sendframe {
  54.     long sync;
  55.     short size;
  56.     unsigned short crc;
  57.     long pkt;
  58.     unsigned char data[PLIP_MTU];
  59. } sendframe, receiveframe;
  60.  
  61. #define SYNCBYTE 0x42
  62.  
  63. struct trackrec {
  64.     struct MinNode n;
  65.     ULONG packettype;
  66.     struct Sana2PacketTypeStats s2ps;
  67. };    
  68.  
  69. struct MyDev {
  70.     struct Library l;
  71.     UBYTE flags, pad;
  72.     APTR seglist;
  73. };
  74.  
  75. struct BufRoutines {
  76.     long __asm (*CopyToBuff)(register __a0 void*,register __a1 void*,register __d0 long);
  77.     long __asm (*CopyFromBuff)(register __a0 void*,register __a1 void*,register __d0 long);
  78. };
  79.  
  80. extern far volatile struct CIA ciaa,ciab;
  81.  
  82. __aligned struct Library *MiscBase, *CIAABase;
  83. struct Library *UtilityBase, *TimerBase;
  84. struct DosLibrary *DOSBase;
  85. struct ExecBase *SysBase;
  86.  
  87. static __aligned struct intdata intdata;
  88. static __aligned struct Interrupt intstruc;
  89. static long allocflags;
  90. static struct MsgPort *serverport, *timerport;
  91. static __aligned struct Sana2DeviceStats devstats; /* device stats */
  92. static __aligned struct timerequest treq;
  93. static __aligned struct List readlist, writelist, eventlist, readorphanlist, tracklist;
  94. static __aligned struct SignalSemaphore eventlistsem, writelistsem, tracklistsem;
  95.  
  96. #define FLG_CLIENT            1    /* client mode */
  97. #define FLG_EXCLUSIVE        2    /* current opener is exclusive */
  98. #define FLG_NOTCONFIGURED    4    /* not configured */
  99. #define FLG_OFFLINE            8
  100. #define ISOFFLINE            (devflags & (FLG_OFFLINE | FLG_NOTCONFIGURED))
  101. static long                    devflags = FLG_NOTCONFIGURED;    /* current flags */
  102.  
  103. #define IM_CLIENT            1    /* client mode */
  104. #define IM_SEND                2    /* sending pkt */
  105. #define IM_REC                4    /* receiving */
  106. #define IM_GETHEADER        8    /* got 1 char */
  107. #define IM_BUFF2            16    /* just filled second buffer */
  108. #define IM_RXERROR            32    /* receive error */
  109. #define IM_GOTSYNC            64
  110.  
  111. extern void intcode(void);
  112. extern void __asm settimeout(register __d0 ULONG timeout);
  113. extern void __asm parinit(register __d0 int);
  114. extern long __asm testbusy(void), testpout(void);
  115. extern void __asm setbusy(register __d0 long), setpout(register __d0 long);
  116.  
  117. extern long __asm waitinputtoggle(void);
  118. extern void __asm setciaoutput(void);
  119. extern void __asm outputtoggle(void);
  120. extern void __asm sampleinput(void);
  121.  
  122. extern USHORT __asm CRC16( register __a0 UBYTE *, register __d0 SHORT );
  123.  
  124. /***********************************************************
  125.  * TRACKTYPE support
  126.  */
  127.  
  128. static struct trackrec * __inline findtracktype( ULONG type )
  129. {
  130.     struct trackrec * tr = ( struct trackrec * ) tracklist.lh_Head;
  131.  
  132.     while( tr->n.mln_Succ )
  133.     {
  134.         if( tr->packettype == type )
  135.             return( tr );
  136.         tr = ( struct trackrec * ) tr->n.mln_Succ;
  137.     }
  138.  
  139.     return( NULL );
  140. }
  141.  
  142. static int addtracktype( ULONG type )
  143. {
  144.     struct trackrec *tr;
  145.  
  146.     ObtainSemaphore( &tracklistsem );
  147.     tr = findtracktype( type );
  148.     if( tr )
  149.     {
  150.         ReleaseSemaphore( &tracklistsem );
  151.         return( -1 );
  152.     }
  153.     else
  154.     {
  155.         tr = AllocMem( sizeof( *tr ), MEMF_CLEAR );
  156.         if( !tr )
  157.         {
  158.             ReleaseSemaphore( &tracklistsem );
  159.             return( -2 );
  160.         }
  161.         tr->packettype = type;
  162.         AddTail( &tracklist, ( struct Node * ) tr );
  163.     }
  164.  
  165.     ReleaseSemaphore( &tracklistsem );
  166.     return( 0 );
  167. }
  168.  
  169. static int remtracktype( ULONG type )
  170. {
  171.     struct trackrec *tr;
  172.  
  173.     ObtainSemaphore( &tracklistsem );
  174.  
  175.     tr = findtracktype( type );
  176.     if( tr )
  177.     {
  178.         Remove( ( struct Node * ) tr );
  179.         FreeMem( tr, sizeof( *tr ) );
  180.         ReleaseSemaphore( &tracklistsem );
  181.         return( 0 );
  182.     }
  183.     ReleaseSemaphore( &tracklistsem );
  184.     return( -1 );
  185. }
  186.  
  187. static void __inline dotracktype( ULONG type, ULONG ps, ULONG pr, ULONG bs, ULONG br, ULONG pd )
  188. {
  189.     struct trackrec * tr;
  190.  
  191.     ObtainSemaphoreShared( &tracklistsem );
  192.     tr = findtracktype( type );    
  193.     if( tr )
  194.     {
  195.         tr->s2ps.PacketsSent += ps;
  196.         tr->s2ps.PacketsReceived += pr;
  197.         tr->s2ps.BytesSent += bs;
  198.         tr->s2ps.BytesReceived += br;
  199.         tr->s2ps.PacketsDropped += pd;
  200.     }
  201.     ReleaseSemaphore( &tracklistsem );
  202. }
  203.  
  204. static int gettrackrec( ULONG type, APTR info )
  205. {
  206.     struct trackrec * tr;
  207.  
  208.     ObtainSemaphoreShared( &tracklistsem );
  209.     tr = findtracktype( type );    
  210.     if( tr )
  211.     {
  212.         memcpy( info, &tr->s2ps, sizeof( tr->s2ps ) );
  213.         ReleaseSemaphore( &tracklistsem );
  214.         return( 0 );
  215.     }
  216.     ReleaseSemaphore( &tracklistsem );
  217.     return( -1 );
  218. }
  219.  
  220. /***********************************************************
  221.  * CIA Zugriff
  222.  */
  223.  
  224. static void __inline writecia( unsigned char val )
  225. {
  226.     ciaa.ciaprb = val;
  227. }
  228.  
  229. static unsigned char __inline readciabyte( void )
  230. {
  231.     return( ciaa.ciaprb );
  232. }
  233.  
  234.  
  235. /***********************************************************
  236.  * Event-Handling: Alle Event-Requests zurückschicken,
  237.  * die auf das eingetretene Ereignis passen.
  238.  */
  239.  
  240. void DoEvent( long event )
  241. {
  242.     struct IOSana2Req *ior, *ior2;
  243.  
  244.     ObtainSemaphore( &eventlistsem );
  245.     
  246.     for( ior = (struct IOSana2Req *) eventlist.lh_Head;
  247.          ior2 = (struct IOSana2Req *) ior->ios2_Req.io_Message.mn_Node.ln_Succ;
  248.          ior = ior2 )
  249.     {
  250.         if( ior->ios2_WireError & event )
  251.         {
  252.             Remove( ior );
  253.             ReplyMsg( ior );
  254.         }
  255.     }
  256.     
  257.     ReleaseSemaphore( &eventlistsem );
  258. }
  259.  
  260.  
  261. /***********************************************************
  262.  * Interrupt Support
  263.  */
  264.  
  265. static void __inline disableint( void )
  266. {
  267.     AbleICR( CIAABase, CIAICRF_FLG );
  268. }
  269.  
  270. static void __inline enableint( void )
  271. {
  272.     AbleICR( CIAABase, CIAICRF_FLG | CIAICRF_SETCLR );
  273. }
  274.  
  275.  
  276. static long setupint( void )
  277. {
  278.     MiscBase = OpenResource( "misc.resource" );
  279.     CIAABase = OpenResource( "ciaa.resource" );
  280.  
  281.     /* Parallel-Port allokieren */
  282.     if( AllocMiscResource( MR_PARALLELPORT, "plip.device" ) ) return 1;
  283.     allocflags |= 1;
  284.     if( AllocMiscResource( MR_PARALLELBITS, "plip.device" ) ) return 2;
  285.     allocflags |= 2;
  286.  
  287.     intstruc.is_Node.ln_Type = NT_INTERRUPT;
  288.     intstruc.is_Node.ln_Pri  = 0;
  289.     intstruc.is_Node.ln_Name = "PLIP PORTS Interrupt";
  290.     intstruc.is_Data         = &intdata;
  291.     intstruc.is_Code         = intcode;
  292.  
  293.     /* Interrupt einfügen */
  294.     Disable();
  295.     {
  296.         /* Parallel-Port initialisieren */
  297.         parinit( intdata.mode & IM_CLIENT );
  298.         
  299.         if( AddICRVector( CIAABase, CIAICRB_FLG, &intstruc ) )
  300.         {
  301.             Enable();
  302.             return 3;
  303.         }
  304.         
  305.         allocflags |= 4;
  306.     }
  307.     Enable();
  308.  
  309.     enableint();
  310.     
  311.     return 0;
  312. }
  313.  
  314. static void cleanupint( void )
  315. {
  316.     if( allocflags & 4 ) RemICRVector( CIAABase, CIAICRB_FLG, &intstruc );
  317.     if( allocflags & 2 ) FreeMiscResource( MR_PARALLELBITS );
  318.     if( allocflags & 1 ) FreeMiscResource( MR_PARALLELPORT );
  319.     allocflags = 0;
  320. }
  321.  
  322.  
  323. /***********************************************************
  324.  * WRITE
  325.  *
  326.  * Der Leser steuert über POUT (bzw. BUSY) die Übertragung.
  327.  * Init: Schreiber schreibt Byte 1, was beim Leser einen Interrupt
  328.  * auslöst. Der Leser quittiert den Empfang jedes Bytes mit einem Wechsel
  329.  * der Handshake-Leitung, der Schreiber zeigt dem Leser durch Wechsel
  330.  * der anderen Handshake-Leitung an, wenn ein Byte bereit steht.
  331.  *
  332.  * Um Deadlocks zu vermeiden (race condition) wird _einmal_ _vor_ der
  333.  * Übertragung der Zustand des Handshakes eingelesen und dann immer
  334.  * nur noch ohne vorherigen Lesezugriff auf den Wechsel gewartet.
  335.  */
  336.  
  337. /* Falls beim Warten auf die Lesebestätigung ein Timeout passiert: */
  338. #define ABORTWRITE { \
  339.     DoEvent( S2EVENT_ERROR | S2EVENT_TX ); \
  340.     intdata.mode &= ~IM_SEND; \
  341.     parinit( intdata.mode & IM_CLIENT ); \
  342.     enableint(); \
  343.     return(-1); }
  344.  
  345. static long procwrite( unsigned char *data, long size )
  346. {
  347.     /* Init */
  348.     disableint();
  349.     setciaoutput();
  350.     
  351.     /* aktuellen Stand der Handshake-Leitung samplen */
  352.     sampleinput();
  353.     
  354.     /* Übertragung anstoßen */
  355.     writecia( *data++ );
  356.  
  357.     while( --size )
  358.     {
  359.         if( !waitinputtoggle() ) ABORTWRITE;
  360.         writecia( *data++ );
  361.         outputtoggle();
  362.     }
  363.  
  364.     /* Bestätigung für letztes Byte abwarten */
  365.     if( !waitinputtoggle() ) ABORTWRITE;
  366.     
  367.     /* Ok. */
  368.     intdata.mode &= ~IM_SEND;
  369.     parinit( intdata.mode & IM_CLIENT );
  370.     enableint();
  371.     devstats.PacketsSent++;
  372.  
  373.     return 0;
  374. }
  375.  
  376.  
  377. /***********************************************************
  378.  * READ
  379.  *
  380.  * Wird vom Interrupt aus angestoßen.
  381.  */
  382.  
  383. /* Falls beim Warten auf das nächste Byte ein Timeout passiert: */
  384. #define ABORTREAD { \
  385.     devstats.BadData++; \
  386.     DoEvent( S2EVENT_ERROR | S2EVENT_RX ); \
  387.     intdata.mode &= ~IM_REC; \
  388.     parinit( intdata.mode & IM_CLIENT ); \
  389.     enableint(); \
  390.     return; }
  391.  
  392. static void procread( void )
  393. {
  394.     unsigned short crc;
  395.     short len;
  396.     int l;
  397.     long bufferror,pkttyp;
  398.  
  399.     struct IOSana2Req *got, *ro;
  400.     unsigned char *d, ch;
  401.  
  402.     /* Init */
  403.     disableint();
  404.     sampleinput();
  405.     
  406.     /* SYNC? */
  407.     if( readciabyte() != 0x42 ) ABORTREAD;
  408.     
  409.     /* restliche SYNC-Bytes überlesen */
  410.     for(;;)
  411.     {
  412.         outputtoggle();
  413.         if( !waitinputtoggle() ) ABORTREAD;
  414.         
  415.         if( (ch = readciabyte()) != 0x42 )
  416.             break;
  417.     }
  418.  
  419.     /* Größe des Packets einlesen */
  420.     d = (unsigned char *) &receiveframe.size;
  421.     *d++ = ch;
  422.     outputtoggle();
  423.     
  424.     if( !waitinputtoggle() ) ABORTREAD;
  425.     *d++ = readciabyte();
  426.     outputtoggle();
  427.  
  428.     /* Packetgröße sinnvoll? */
  429.     len = receiveframe.size;
  430.     if( len < 6 || len > plip_mtu+6 ) ABORTREAD;
  431.  
  432.     /* len Bytes einlesen */
  433.     while( len-- )
  434.     {
  435.         if( !waitinputtoggle() ) ABORTREAD;
  436.         *d++ = readciabyte();
  437.         outputtoggle();
  438.     }
  439.     
  440.     /* fertig mit Lesen */
  441.     intdata.mode &= ~IM_REC;
  442.  
  443.     /* Exit */
  444.     parinit( intdata.mode & IM_CLIENT );
  445.     enableint();
  446.     
  447.     /* CRC check */
  448.     pkttyp = receiveframe.pkt;
  449.     l = receiveframe.size - 6;
  450.     d = receiveframe.data;
  451.  
  452.     crc = CRC16( d, l );
  453.  
  454.     if( crc == receiveframe.crc )
  455.     {
  456.         /* CRC OK! */
  457.  
  458.         devstats.PacketsReceived++;
  459.  
  460.         dotracktype( pkttyp, 0, 1, 0, l, 0 );
  461.         
  462.         for( got = (struct IOSana2Req *) readlist.lh_Head;
  463.              got && got->ios2_Req.io_Message.mn_Node.ln_Succ;
  464.              got = (struct IOSana2Req *) got->ios2_Req.io_Message.mn_Node.ln_Succ )
  465.         {
  466.             if( got->ios2_PacketType == pkttyp )
  467.             {
  468.                 /* Hurra, der will's haben! */
  469.                 Remove( got );
  470.                 
  471.                 /* Daten kopieren */
  472.                 bufferror = ((struct BufRoutines *) got->ios2_BufferManagement)
  473.                     -> CopyToBuff( got->ios2_Data, receiveframe.data, receiveframe.size - 6 );
  474.                 
  475.                 /* Fehler? */
  476.                 if( !bufferror )
  477.                 {
  478.                     got->ios2_Error     = S2ERR_SOFTWARE;
  479.                     got->ios2_WireError = S2WERR_BUFF_ERROR;
  480.                 }
  481.                 else
  482.                 {
  483.                     got->ios2_Error = got->ios2_WireError = 0;
  484.                 }
  485.  
  486.                 /* Request befriedigen */
  487.                 got->ios2_Flags      = 0;
  488.                 got->ios2_SrcAddr[0] = (devflags & FLG_CLIENT) ?  0     : (1<<7);
  489.                 got->ios2_DstAddr[0] = (devflags & FLG_CLIENT) ? (1<<7) :  0    ;
  490.                 got->ios2_DataLength = receiveframe.size - 6;
  491.                 ReplyMsg( got );
  492.                 
  493.                 /* und 'raus */
  494.                 got=0;
  495.                 break;
  496.             }
  497.         }
  498.     }
  499.     else
  500.     {
  501.         /* CRC ERROR! */
  502.  
  503.         /* Clients Bescheid sagen, daß Müll ankam */
  504.         DoEvent( S2EVENT_ERROR | S2EVENT_RX );
  505.         
  506.         got = 0;
  507.         devstats.BadData++;
  508.     }
  509.     
  510.     if( got )
  511.     {
  512.         /* Hm... wir haben ein Packet bekommen, das keiner haben will... */
  513.         devstats.UnknownTypesReceived++;
  514.         
  515.         /* ...aber vielleicht ist da ja jemand, der genau solche Packets auffängt: */
  516.         if( ro = (struct IOSana2Req *) RemHead( &readorphanlist ) )
  517.         {
  518.             /* Packet komplett kopieren */
  519.             bufferror = ((struct BufRoutines *) ro->ios2_BufferManagement)
  520.                 -> CopyToBuff( ro->ios2_Data, &receiveframe.pkt, receiveframe.size - 2 );
  521.             
  522.             /* Fehler? */
  523.             if( !bufferror )
  524.             {
  525.                 ro->ios2_Error     = S2ERR_SOFTWARE;
  526.                 ro->ios2_WireError = S2WERR_BUFF_ERROR;
  527.             }
  528.             else
  529.             {
  530.                 ro->ios2_Error = ro->ios2_WireError = 0;
  531.             }
  532.             
  533.             /* Request befriedigen */
  534.             ro->ios2_Flags      = 0;
  535.             ro->ios2_SrcAddr[0] = (devflags & FLG_CLIENT) ?  0     : (1<<7);
  536.             ro->ios2_DstAddr[0] = (devflags & FLG_CLIENT) ? (1<<7) :  0    ;
  537.             ro->ios2_DataLength = receiveframe.size - 2;
  538.             ReplyMsg( ro );
  539.         }
  540.  
  541.         /* Noe, also entsorgen */
  542.         dotracktype( pkttyp, 0, 0, 0, 0, 1 );
  543.  
  544.     }
  545.     
  546. }
  547.  
  548. /***********************************************************
  549.  * READARGS - reads Prefs file
  550.  */
  551.  
  552. static void __saveds readargs( void )
  553. {
  554.     struct RDArgs *rda;
  555.     struct args {
  556.         ULONG *timeout;
  557.         LONG *priority;
  558.         ULONG *mtu;
  559.         ULONG *bps;
  560.         ULONG *retries;
  561.     } args = { 0 };
  562.     BPTR plipvar = Open( "ENV:Sana2/plip.config", MODE_OLDFILE );
  563.     BPTR oldinput, infowin, oldoutput;
  564.     
  565.     infowin = Open( "CON://340/146/PLIP 38.12/NOSIZE/INACTIVE", MODE_NEWFILE );
  566.     
  567.     if( infowin )
  568.     {
  569.         FPrintf( infowin,
  570.             "\x1b[0 p\n"
  571.             "\x1b[1mPLIP 38.12\x1b[0m " __AMIGADATE__ "\n"
  572.             "by \x1b[3mOliver Wagner\x1b[0m & \x1b[3mMichael Balzer\x1b[0m\n"
  573.             "S2_DEVICEQUERY fixed by R. Jeremy James\n"
  574.             "Freeware -- see manual!\n\n" );
  575.     }
  576.     
  577.     if( !plipvar )
  578.         goto xit;
  579.  
  580.     oldinput = SelectInput( plipvar );
  581.     
  582.     rda = ReadArgs( "TIMEOUT/K/N,PRIORITY=PRI/K/N,MTU/K/N,BPS/K/N,RETRIES/K/N" , (LONG *)&args, NULL );
  583.     
  584.     if(rda)
  585.     {
  586.         if(args.timeout)
  587.         {
  588.             settimeout( *args.timeout );
  589.             if( infowin ) FPrintf(infowin, " Timeout.: %lx/%ld\n", *args.timeout, *args.timeout);
  590.         }
  591.         if(args.priority)
  592.         {
  593.             SetTaskPri( FindTask(SERVER_TASK), *args.priority);
  594.             if( infowin ) FPrintf(infowin, " Priority: %ld\n", *args.priority);
  595.         }
  596.         if( args.mtu )
  597.         {
  598.             if( *args.mtu <= PLIP_MTU )
  599.             {
  600.                 plip_mtu = *args.mtu;
  601.                 if( infowin ) FPrintf(infowin, " MTU: %ld\n", *args.mtu);
  602.             }
  603.         }
  604.         if( args.bps )
  605.         {
  606.             plip_bps = *args.bps;
  607.             if( infowin ) FPrintf(infowin, " BPS: %ld\n", *args.bps);
  608.         }
  609.         if( args.retries )
  610.         {
  611.             if( *args.retries <= 127 )
  612.             {
  613.                 plip_retries = *args.retries;
  614.                 if( infowin ) FPrintf(infowin, " Max Retries: %ld\n", *args.retries);
  615.             }
  616.         }
  617.         FreeArgs( rda );
  618.     }
  619.     else if(infowin)
  620.     {
  621.         oldoutput = SelectOutput( infowin );
  622.         PrintFault( IoErr(), "\x07 PLIP");
  623.         SelectOutput( oldoutput );
  624.     }
  625.  
  626.     Close( SelectInput( oldinput ));
  627.  
  628. xit:
  629.     /* Wake up Main server */
  630.     Signal( intdata.sigtask, SIGBREAKF_CTRL_E );
  631.  
  632.     if( infowin )
  633.     {
  634.         Delay( 10*50 );
  635.         Close( infowin );
  636.     }
  637.  
  638. }
  639.  
  640.  
  641.  
  642. /***********************************************************
  643.  * MAINLOOP - Device Dispatcher
  644.  */
  645.  
  646. static void __saveds servertask( void )
  647. {
  648.     long portsig, s, timersig;
  649.     struct IOSana2Req *currentwrite = 0, *got, *nextwrite;
  650.     long timerqueued = 0, readstart = 0x42, bufferror;
  651.  
  652.     /*
  653.      * Setup
  654.      */
  655.     
  656.     s = AllocSignal( -1 );
  657.     intdata.recsig = 1L << s;
  658.     
  659.     serverport = CreateMsgPort();
  660.     timerport  = CreateMsgPort();
  661.     portsig  = 1 << serverport->mp_SigBit;
  662.     timersig = 1 << timerport->mp_SigBit;
  663.     
  664.     NewList( &readlist );    
  665.     NewList( &writelist );
  666.     NewList( &eventlist );
  667.     NewList( &readorphanlist );
  668.     NewList( &tracklist );
  669.     
  670.     InitSemaphore( &eventlistsem );
  671.     InitSemaphore( &writelistsem );
  672.     InitSemaphore( &tracklistsem );
  673.     
  674.     treq.tr_node.io_Message.mn_ReplyPort = timerport;
  675.     OpenDevice( "timer.device", UNIT_VBLANK, &treq, 0 );
  676.     TimerBase = (struct Library *) treq.tr_node.io_Device;
  677.     GetSysTime( &devstats.LastStart );
  678.  
  679.     CreateNewProcTags(
  680.         NP_Entry, readargs,
  681.         NP_Name, "PLIP Arg Parser Process",
  682.         NP_Priority, 5,
  683.         NP_WindowPtr, -1,
  684.         TAG_DONE
  685.     );
  686.  
  687.     /* Wait for reply from Arg Parser */
  688.     Wait( SIGBREAKF_CTRL_E );
  689.  
  690.     for(;;)
  691.     {
  692.  
  693.         /* Wir lassen uns regelmäßig vom timer.device aufwecken, damit
  694.          * keine Senderequests liegen bleiben, wenn wir nicht sofort
  695.          * die Leitung bekommen können
  696.          */
  697.         if( !timerqueued )
  698.         {
  699.             treq.tr_time.tv_secs    = 2 + (devflags & FLG_CLIENT);
  700.             treq.tr_time.tv_micro   = 0;
  701.             treq.tr_node.io_Command = TR_ADDREQUEST;
  702.             SendIO( &treq );
  703.             timerqueued = 1;
  704.         }
  705.         
  706.         s = Wait( intdata.recsig | portsig | timersig );
  707.  
  708.         if( s & intdata.recsig )
  709.         {
  710.             /* Interrupt: Packet empfangen */
  711.             procread();
  712.         }
  713.         
  714.         if( s & timersig )
  715.         {
  716.             /* Aufwecksignal */
  717.             AbortIO( &treq );
  718.             WaitIO( &treq );
  719.             timerqueued = 0;
  720.         }
  721.         
  722.         if( s & portsig )
  723.         {
  724.             /* Kommandos (Requests) entgegennehmen */
  725.             
  726.             while( got = (struct IOSana2Req *) GetMsg( serverport ) )
  727.             {
  728.  
  729.                 if( got->ios2_Req.io_Command == CMD_READ )
  730.                     AddTail( &readlist, got );
  731.                 else if( got->ios2_Req.io_Command == S2_READORPHAN )
  732.                     AddTail( &readorphanlist, got );
  733.                 else
  734.                 {
  735.                     ObtainSemaphore( &writelistsem );
  736.                     AddTail( &writelist, got );
  737.                     ReleaseSemaphore( &writelistsem );
  738.                 }
  739.             }
  740.         }
  741.  
  742.         /*
  743.          * So, Signale alle erledigt; haben wir 'was zu schreiben?
  744.          */
  745.         
  746.         ObtainSemaphore( &writelistsem );
  747.         
  748.         for( currentwrite = (struct IOSana2Req *) writelist.lh_Head;
  749.              nextwrite = (struct IOSana2Req *) currentwrite->ios2_Req.io_Message.mn_Node.ln_Succ;
  750.              currentwrite = nextwrite )
  751.         {
  752.  
  753.             /* Inzwischen ein Read-Interrupt? */
  754.             if( SetSignal(0,0) & intdata.recsig) break;
  755.  
  756.             /* Arbitration */
  757.             if( devflags & FLG_CLIENT )
  758.             {
  759.                 /* Leitung frei? */
  760.                 if( !testbusy() )
  761.                     break;        /* später nochmal versuchen */
  762.                 
  763.                 /* Sende-Status setzen */
  764.                 setpout( 1 );
  765.                 
  766.                 /* Leitung immer noch frei? */
  767.                 if( !testbusy() )
  768.                 {
  769.                     setpout( 0 );
  770.                     break;        /* später nochmal versuchen */
  771.                 }
  772.             }
  773.             else
  774.             {
  775.                 /* Leitung frei? */
  776.                 if( testpout() )
  777.                     break;        /* später nochmal versuchen */
  778.                 
  779.                 /* Sende-Status setzen */
  780.                 setbusy( 0 );
  781.                 
  782.                 /* Leitung immer noch frei? */
  783.                 if( testpout() )
  784.                 {
  785.                     /*setbusy( 1 );*/
  786.                     break;        /* später nochmal versuchen */
  787.                 }
  788.             }
  789.             
  790.             /* Gut, wir können beginnen zu senden */
  791.             
  792.             /* Daten kopieren */
  793.             bufferror = ((struct BufRoutines *) currentwrite->ios2_BufferManagement)
  794.                 -> CopyFromBuff( sendframe.data, currentwrite->ios2_Data, currentwrite->ios2_DataLength );
  795.             
  796.             /* Fehler? */
  797.             if( !bufferror )
  798.             {
  799.                 currentwrite->ios2_Error     = S2ERR_SOFTWARE;
  800.                 currentwrite->ios2_WireError = S2WERR_BUFF_ERROR;
  801.                 Remove( currentwrite );
  802.                 ReplyMsg( currentwrite );
  803.                 continue;
  804.                 /* weiter mit nächstem Write-Req */
  805.             }
  806.             
  807.             /* Packet-Header füllen */
  808.             sendframe.sync = 0x42424242;
  809.             sendframe.pkt  = currentwrite->ios2_PacketType;
  810.             sendframe.size = currentwrite->ios2_DataLength + 6;
  811.             
  812.             /* CRC berechnen und einsetzen */
  813.             {
  814.                 int l = currentwrite->ios2_DataLength;
  815.                 unsigned char *d = sendframe.data;
  816.                 unsigned short crc = 0;
  817.  
  818.                 crc = CRC16( d, l );
  819.  
  820.                 sendframe.crc = crc;
  821.             }
  822.             
  823.             /* Packet Senden */
  824.  
  825.             readstart = procwrite( (char *) &sendframe, sendframe.size + 6 );
  826.  
  827.             if( !readstart )
  828.             {
  829.                 /* Packet erfolgreich gesendet */
  830.                 dotracktype( sendframe.pkt, 1, 0, currentwrite->ios2_DataLength, 0, 0 );
  831.                 currentwrite->ios2_Error = currentwrite->ios2_WireError = 0;
  832.                 Remove( currentwrite );
  833.                 ReplyMsg( currentwrite );
  834.             }
  835.             else
  836.             {
  837.                 /* Fehler; WriteRetryCounter erhöhen */
  838.                 if( ( currentwrite->ios2_Error++ ) > plip_retries )
  839.                 {
  840.                     /* Maximale Fehleranzahl erreicht */
  841.                     currentwrite->ios2_Error         = S2ERR_BAD_STATE;
  842.                     currentwrite->ios2_WireError    = S2WERR_GENERIC_ERROR;
  843.                     Remove( currentwrite );
  844.                     ReplyMsg( currentwrite );
  845.                 }
  846.                 break;
  847.             }
  848.         }
  849.         
  850.         ReleaseSemaphore( &writelistsem );
  851.         
  852.         /* Alle Signale bearbeitet */
  853.     }
  854. }
  855.  
  856.  
  857. /************************************************************
  858.  * DEVICE-Management und -Support
  859.  */
  860.  
  861. long __asm __saveds DevOpen( register __a1 struct IOSana2Req *ior,
  862.     register __d0 long unit, register __d1 long flags,
  863.     register __a6 struct MyDev *devnode )
  864. {
  865.     struct TagItem *ti;
  866.     struct BufRoutines *br;
  867.  
  868.     devnode->l.lib_OpenCnt++;    /* Expunge-Schutz */
  869.  
  870.     if( unit < 0 || unit > 1 )
  871.     {
  872.         devnode->l.lib_OpenCnt--;
  873.         ior->ios2_Req.io_Error  = -1;
  874.         ior->ios2_Req.io_Device = (struct Device *) -1;
  875.         return( -1 );
  876.         /* openfailed */ 
  877.     }
  878.  
  879.     /* already open? */
  880.     if( devnode->l.lib_OpenCnt > 1 )
  881.     {
  882.         if( (unit && !(devflags & FLG_CLIENT)) ||
  883.             (flags & SANA2OPF_MINE) )
  884.         {
  885.             /* busy/open */
  886.             devnode->l.lib_OpenCnt--;
  887.             ior->ios2_Req.io_Error  = -1;
  888.             ior->ios2_Req.io_Device = (struct Device *) -1;
  889.             return( -1 );
  890.         }
  891.     }
  892.     
  893.     if( flags & SANA2OPF_MINE )
  894.         devflags     |= FLG_EXCLUSIVE;
  895.     
  896.     if( unit )
  897.     {
  898.         devflags     |= FLG_CLIENT;
  899.         intdata.mode |= IM_CLIENT;
  900.     }
  901.  
  902.     intdata.SysBase=SysBase; /* Clone SysBase */
  903.  
  904.     /* Start Server Process */
  905.     if( !intdata.sigtask ) 
  906.         intdata.sigtask = CreateTask( SERVER_TASK, 15, servertask, 4000);
  907.     
  908.     if( !intdata.sigtask )
  909.     {
  910.         /* kein Task */
  911.         devnode->l.lib_OpenCnt--; 
  912.         ior->ios2_Req.io_Error  = -1;
  913.         ior->ios2_Req.io_Device = (struct Device *) -1;
  914.         return( -1 );
  915.     }
  916.  
  917.     /* Task Setup Done; convert Taglist */
  918.     br = AllocMem( 8, MEMF_CLEAR );
  919.     
  920.     if( ti = FindTagItem(S2_CopyToBuff, ior->ios2_BufferManagement) )
  921.         br->CopyToBuff = ti->ti_Data;
  922.     
  923.     if( ti = FindTagItem(S2_CopyFromBuff, ior->ios2_BufferManagement) )
  924.         br->CopyFromBuff = ti->ti_Data;
  925.  
  926.     if( !br->CopyToBuff || !br->CopyFromBuff )
  927.     {
  928.         FreeMem( br, 8 );
  929.         devnode->l.lib_OpenCnt--; 
  930.         ior->ios2_Req.io_Error  = -1;
  931.         ior->ios2_Req.io_Device = (struct Device *) -1;
  932.         return( -1 );
  933.     }
  934.     
  935.     devnode->l.lib_Flags &= ~LIBF_DELEXP;
  936.     
  937.     ior->ios2_BufferManagement = br;
  938.     ior->ios2_Req.io_Unit = (struct Unit *) br;
  939.     ior->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
  940.     ior->ios2_Req.io_Error = 0;
  941.     return( 0 );
  942. }
  943.  
  944.  
  945. static long goonline( void )
  946. {
  947.     long x;
  948.  
  949.     if( ISOFFLINE )
  950.     {
  951.         if( x = setupint() )
  952.             return( -1 );
  953.         
  954.         devflags &= ~(FLG_OFFLINE | FLG_NOTCONFIGURED);
  955.     }
  956.  
  957.     return( 0 );    
  958. }
  959.  
  960.  
  961. static void gooffline( void )
  962. {
  963.     if( ! (ISOFFLINE) )
  964.     {
  965.         cleanupint();
  966.         devflags |= FLG_OFFLINE;
  967.     }
  968. }
  969.  
  970.  
  971. long __asm __saveds DevExpunge( register __a6 struct MyDev *devnode )
  972. {
  973.     long seglist;
  974.     struct trackrec *trackrec;
  975.  
  976.     if( devnode->l.lib_OpenCnt )
  977.     {
  978.         devnode->l.lib_Flags |= LIBF_DELEXP;
  979.         return( 0 );
  980.     }
  981.     
  982.     gooffline();
  983.     
  984.     if( intdata.sigtask ) RemTask( intdata.sigtask );
  985.     
  986.     if( serverport ) FreeMem( serverport, sizeof(struct MsgPort) );
  987.     if( timerport  ) FreeMem( timerport,  sizeof(struct MsgPort) );
  988.     
  989.     Remove( devnode );
  990.     seglist = (long) devnode->seglist;
  991.     FreeMem( ((char *) devnode) - devnode->l.lib_NegSize,
  992.         devnode->l.lib_PosSize + devnode->l.lib_NegSize );
  993.  
  994.     /* Free tracktype records */
  995.     while( ( trackrec = ( struct trackrec * ) RemHead( &tracklist ) ) )
  996.         FreeMem( trackrec, sizeof( *trackrec ) );
  997.     
  998.     return( seglist );
  999. }
  1000.  
  1001.  
  1002. long __asm __saveds DevClose( register __a1 struct IOSana2Req *ior,
  1003.     register __a6 struct MyDev *devnode )
  1004. {
  1005.     FreeMem( ior->ios2_Req.io_Unit, 8 );
  1006.     
  1007.     ior->ios2_Req.io_Device = (struct Device *) -1;
  1008.     ior->ios2_Req.io_Unit   = (struct Unit   *) -1;
  1009.  
  1010.     if( !(--devnode->l.lib_OpenCnt) ) /* ERROR! */
  1011.     {
  1012.         devflags &= ~FLG_EXCLUSIVE;
  1013.         if( devnode->l.lib_Flags & LIBF_DELEXP )
  1014.             return( DevExpunge(devnode) );
  1015.     }
  1016.     
  1017.     return( 0 );
  1018. }
  1019.  
  1020.  
  1021. void __saveds __asm DevBeginIO( register __a1 struct IOSana2Req *ior )
  1022. {
  1023.     struct Sana2DeviceQuery *devquery;
  1024.  
  1025.     ior->ios2_Error = IOERR_NOCMD;
  1026.     
  1027.     switch( ior->ios2_Req.io_Command )
  1028.     {
  1029.         case S2_GETSTATIONADDRESS:
  1030.             ior->ios2_SrcAddr[0] = ior->ios2_DstAddr[0] = (devflags & FLG_CLIENT) ? 1<<7 : 0;
  1031.             ior->ios2_Error = ior->ios2_WireError = 0;
  1032.             break;
  1033.  
  1034.         case S2_TRACKTYPE:
  1035.             if( addtracktype( ior->ios2_PacketType ) )
  1036.             {
  1037.                 ior->ios2_Error = S2ERR_BAD_STATE;
  1038.                 ior->ios2_WireError = S2WERR_ALREADY_TRACKED;
  1039.             }
  1040.             else
  1041.                 ior->ios2_Error = ior->ios2_WireError = 0;
  1042.             break;
  1043.  
  1044.         case S2_UNTRACKTYPE:
  1045.             if( remtracktype( ior->ios2_PacketType ) )
  1046.             {
  1047.                 ior->ios2_Error = S2ERR_BAD_STATE;
  1048.                 ior->ios2_WireError = S2WERR_NOT_TRACKED;
  1049.             }
  1050.             else
  1051.                 ior->ios2_Error = ior->ios2_WireError = 0;
  1052.             break;
  1053.  
  1054.  
  1055.         case S2_GETTYPESTATS:
  1056.             if( gettrackrec( ior->ios2_PacketType, ior->ios2_StatData ) )
  1057.             {
  1058.                 ior->ios2_Error = S2ERR_BAD_STATE;
  1059.                 ior->ios2_WireError = S2WERR_NOT_TRACKED;
  1060.             }
  1061.             else
  1062.                 ior->ios2_Error = ior->ios2_WireError = 0;
  1063.             break;
  1064.  
  1065.         case S2_GETGLOBALSTATS:
  1066.             memcpy( ior->ios2_StatData, &devstats, sizeof(struct Sana2DeviceStats) );
  1067.             ior->ios2_Error = ior->ios2_WireError = 0;
  1068.             break;
  1069.             
  1070.         case S2_DEVICEQUERY:
  1071.             ior->ios2_Error = ior->ios2_WireError = 0;
  1072.             devquery = ior->ios2_StatData;
  1073.             devquery->DevQueryFormat = devquery->DeviceLevel = 0;
  1074.             
  1075.                         /*    std+com    */
  1076.             if( devquery->SizeAvailable >= 18 ) devquery->AddrFieldSize = 1;
  1077.             if( devquery->SizeAvailable >= 22 ) devquery->MTU           = plip_mtu;
  1078.             if( devquery->SizeAvailable >= 26 ) devquery->BPS           = plip_bps;
  1079.             if( devquery->SizeAvailable >= 30 ) devquery->HardwareType  = PLIP_HWTYPE;
  1080.             
  1081.             devquery->SizeSupplied = min( devquery->SizeAvailable, sizeof(struct Sana2DeviceQuery) );
  1082.             break;
  1083.             
  1084.         case S2_ONLINE:
  1085.             if( goonline() )
  1086.                 ior->ios2_Error = S2ERR_NO_RESOURCES;
  1087.             else
  1088.                 ior->ios2_Error = ior->ios2_WireError = 0;
  1089.             break;
  1090.             
  1091.         case S2_OFFLINE:
  1092.             gooffline();
  1093.             ior->ios2_Error = ior->ios2_WireError = 0;
  1094.             break;
  1095.  
  1096.         case S2_ONEVENT:
  1097.             ObtainSemaphore( &eventlistsem );
  1098.             AddTail( &eventlist, ior );
  1099.             ReleaseSemaphore( &eventlistsem );
  1100.             return;
  1101.  
  1102.         case CMD_READ:
  1103.         case S2_READORPHAN:
  1104.             if( ISOFFLINE )
  1105.             {
  1106.                 ior->ios2_Error     = S2ERR_OUTOFSERVICE;
  1107.                 ior->ios2_WireError = S2WERR_UNIT_OFFLINE;
  1108.                 break;
  1109.             }
  1110.             
  1111.             PutMsg( serverport, ior );
  1112.             return;
  1113.             
  1114.         case CMD_WRITE:
  1115.         case S2_BROADCAST:
  1116.             if( ISOFFLINE )
  1117.             {
  1118.                 ior->ios2_Error     = S2ERR_OUTOFSERVICE;
  1119.                 ior->ios2_WireError = S2WERR_UNIT_OFFLINE;
  1120.                 break;
  1121.             }
  1122.             
  1123.             if( ior->ios2_DataLength > plip_mtu )
  1124.             {
  1125.                 ior->ios2_Error     = S2ERR_MTU_EXCEEDED;
  1126.                 ior->ios2_WireError = 0;
  1127.                 break;
  1128.             }
  1129.  
  1130.             /* 38.10: ios2_Error wird als WriteRetryCounter benutzt */
  1131.  
  1132.             ior->ios2_Error = 0;
  1133.             
  1134.             PutMsg( serverport, ior );
  1135.             return;
  1136.             
  1137.         case S2_CONFIGINTERFACE:
  1138.             if( devflags & FLG_NOTCONFIGURED )
  1139.             {
  1140.                 ior->ios2_SrcAddr[0] = (devflags & FLG_CLIENT) ? (1<<7) : 0;
  1141.                 
  1142.                 if( goonline() )
  1143.                 {
  1144.                     ior->ios2_Error     = S2ERR_NO_RESOURCES;
  1145.                     ior->ios2_WireError = 0;
  1146.                 }
  1147.                 else
  1148.                 {
  1149.                     ior->ios2_Error = ior->ios2_WireError = 0;
  1150.                 }
  1151.                 
  1152.                 break;
  1153.             }
  1154.             
  1155.             ior->ios2_Error     = S2ERR_SOFTWARE;
  1156.             ior->ios2_WireError = S2WERR_IS_CONFIGURED;
  1157.             break;
  1158.     }
  1159.  
  1160.     ior->ios2_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
  1161.     return;
  1162. }
  1163.  
  1164.  
  1165. static long isinlist( struct Node *n, struct List *l )
  1166. {
  1167.     struct Node *cmp = l->lh_Head;
  1168.  
  1169.     while( cmp != n && cmp->ln_Succ )
  1170.         cmp = cmp->ln_Succ;
  1171.     
  1172.     return( cmp == n );
  1173. }
  1174.  
  1175.  
  1176. long __asm __saveds DevAbortIO( register __a1 struct IOSana2Req *ior )
  1177. {
  1178.     Forbid();
  1179.     
  1180.     if( isinlist(ior, &eventlist) ||
  1181.         isinlist(ior, &readlist)  ||
  1182.         isinlist(ior, &readorphanlist) )
  1183.     {
  1184.         Remove( ior );
  1185.         ior->ios2_Error     = IOERR_ABORTED;
  1186.         ior->ios2_WireError = 0;
  1187.         ReplyMsg( ior );
  1188.         Permit();
  1189.         return( 0 );
  1190.     }
  1191.     else
  1192.     {
  1193.         ObtainSemaphore( &writelistsem );
  1194.         
  1195.         if( isinlist(ior, &writelist) )
  1196.         {
  1197.             Remove( ior );
  1198.             ReleaseSemaphore( &writelistsem );
  1199.             
  1200.             ior->ios2_Error     = IOERR_ABORTED;
  1201.             ior->ios2_WireError = 0;
  1202.             
  1203.             ReplyMsg( ior );
  1204.             Permit();
  1205.             return( 0 );
  1206.         }
  1207.         
  1208.         ReleaseSemaphore( &writelistsem );
  1209.     }
  1210.     
  1211.     Permit();
  1212.     
  1213.     return( -1 );
  1214. }
  1215.  
  1216. /* EOF */
  1217.